﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices.WindowsRuntime;
using System.Text;
using System.Threading.Tasks;
using StyleMVVM.Data.Activation;

namespace StyleMVVM.DependencyInjection
{
	/// <summary>
	/// IActivationStrategy provides a mechanism to instantiate a particular export
	/// a strategy can be exported under many names and types.
	/// </summary>
	public interface IExportStrategy : IExportActivator
	{
		/// <summary>
		/// Names this strategy should be known as.
		/// </summary>
		IEnumerable<string> ExportNames { get; set; }

		/// <summary>
		/// Types this strategy is exported under
		/// </summary>
		IEnumerable<Type> ExportedTypes { get; set; }

		/// <summary>
		/// Type to activate
		/// </summary>
		Type ActivationType { get; }

		/// <summary>
		/// Marking an export as externally owned will tell the framework not to dispose of the export when it goes out of scope
		/// </summary>
		bool ExternallyOwned { get; set; }

		/// <summary>
		/// If your export implements IDisposable and is used in a IDisposalScope then this method allows you to inject cleanup logic before disposal
		/// The use case for this is something like closing a wcf proxy before disposing it
		/// </summary>
		BeforeDisposalCleanupDelegate DisposalCleanupDelegate { get; set; }

		/// <summary>
		/// This is the default life cycle container for this strategy. If null then the export will be created new each time.
		/// </summary>
		ILifeCycleContainer LifeCycleContainer { get; set; }

		/// <summary>
		/// should this object type be registered for suspension
		/// </summary>
		bool Suspendable { get; set; }

		/// <summary>
		/// What environement is this strategy being exported under.
		/// </summary>
		ExportEnvironment Environment { get; set; }

		/// <summary>
		/// What export priority is this being exported as
		/// </summary>
		int Priority { get; set; }

		/// <summary>
		/// True when the object being exported should be part of Core application
		/// </summary>
		bool IsCoreExport { get; set; }

		/// <summary>
		/// The order in which the core exports should be started.
		/// </summary>
		int CoreExportStartOrder { get; set; }

		/// <summary>
		/// Initialize the strategy
		/// </summary>
		void Initialize();

		/// <summary>
		/// Adds a new pipeline handler to the strategy
		/// </summary>
		/// <param name="pipelineHandler"></param>
		void AddPiplineHandler(IExportPipelineHandler pipelineHandler);

		/// <summary>
		/// Removes the specified pipelined handler from the strategy
		/// </summary>
		/// <param name="pipelineHandler"></param>
		void RemovePipelineHandler(IExportPipelineHandler pipelineHandler);

		/// <summary>
		/// Test if the export meets the condition
		/// </summary>
		/// <param name="container"></param>
		/// <param name="injectionContext"></param>
		/// <returns></returns>
		bool MeetsConditions(IDependencyInjectionContainer container, IInjectionContext injectionContext);

		/// <summary>
		/// Add a condition to the export
		/// </summary>
		/// <param name="condition"></param>
		void AddCondition(IExportCondition condition);

		/// <summary>
		/// Remove a condition from the export
		/// </summary>
		/// <param name="condition"></param>
		void RemoveCondition(IExportCondition condition);

		/// <summary>
		/// Gets all conditions for the export
		/// </summary>
		/// <returns></returns>
		IEnumerable<IExportCondition> Conditions();

		/// <summary>
		/// List of metadata associated with this strategy
		/// </summary>
		/// <returns></returns>
		IEnumerable<KeyValuePair<string, object>> Metadata { get; set; }

		/// <summary>
		/// List of enrich with delegates
		/// </summary>
		IEnumerable<EnrichWithDelegate> EnrichWithDelegates { get; set; }
	}

	/// <summary>
	/// This class represnets an open generic strategy that will be used to 
	/// close and create another strategy.
	/// </summary>
	public interface IGenericActivationStrategy : IExportStrategy
	{
		IExportStrategy CreateClosedStrategy(Type tType);
	}
}